#ifndef _NAMED_VECTOR_H_
#define _NAMED_VECTOR_H_

#include "crc32.h"
#include <list>

namespace num
{
/// provides a container using CRC32 to generate Hashes of names
template <class T> class NamedList
{
public:
	NamedList(bool DeleteSet = true, bool IgnoreCase = true ) :
		m_DeleteSet(DeleteSet),
		m_IgnoreCase(IgnoreCase)
	{
		

	}
				
	virtual ~NamedList( )
	{
		if (m_DeleteSet)
		{
			ClearSet();
		}
	}


	void			ClearSet()
	{
		if (m_DeleteSet)
		{
			for (typename ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
			{
				delete (*It).second;
			}
		}
		m_Set.resize(0);
	}

	/// add element to end of set
	bool			AddElementBack(const std::string& Name, T	Value)
	{
		if (!ElementExists(Name))
		{	
			Element NewElement;
			NewElement.second = Value;
			NewElement.key  = Getkey(Name);
			m_Set.push_back(NewElement);

			return true;
		}
		return false;
	}
	
	/// add element to front of set
	bool			AddElementFront(const std::string& Name, T	Value)
	{
		if (!ElementExists(Name))
		{	
			Element NewElement;
			NewElement.second = Value;
			NewElement.key  = Getkey(Name);
			m_Set.push_front(NewElement);
			return true;
		}
		return false;
	}


	/// add element to in front of element
	bool			InsertBefore(const std::string& Name, T	Value, const std::string& RelativeTo)
	{
		if (!ElementExists(Name))
		{	
			if (ElementExists(RelativeTo))
			{
				unsigned long	key = Getkey(RelativeTo);
				for (typename ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
				{
					if ((*It).key == key) 
					{
						Element NewElement;
						NewElement.second = Value;
						NewElement.key  = Getkey(Name);
						m_Set.insert(It, NewElement);

						return true;
					}
				}
			}
			return AddElementBack(Name, Value);
		}
		return false;
	}

	/// add element after element
	bool			InsertAfter(const std::string& Name, T	Value, const std::string& RelativeTo)
	{
		if (!ElementExists(Name))
		{	
			if (ElementExists(RelativeTo))
			{
				unsigned long	key = Getkey(RelativeTo);
				bool			InsertNext = false;

				for (typename ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
				{
					if (InsertNext)
					{
						Element NewElement;
						NewElement.second = Value;
						NewElement.key  = Getkey(Name);
						m_Set.insert(It, NewElement);

						return true;
					}
					if ((*It).key == key) 
					{
						InsertNext = true;
					}
				}
			}
			return AddElementBack(Name, Value);
		}
		return false;
	}

	/// check if element exists
	bool			ElementExists(const std::string& Name) const
	{
		if (GetElement(Name) != NULL)
			return true;
		return false;
	}
	
	/// retrieve the element
	T				GetElement(const std::string& Name) const
	{
		unsigned long	key = Getkey(Name);
		return GetElement(key);
	}
	/// retrieve the element by key.. usefull for caching the key
	T				GetElement(unsigned long key) const
	{
		for (typename ElementList::const_iterator It = m_Set.begin(); It != m_Set.end(); It++)
		{
			if ((*It).key == key) return (*It).second;
		}
		return NULL;
	}
	/// delete the element
	void			RemoveElement(unsigned long key, bool Delete = true)
	{
		for (typename ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
		{
			if ((*It).key == key) 
			{
				if (Delete && m_DeleteSet)
				{
					delete (*It).second;
				}
				m_Set.erase(It);
				return;
			}
		}
	}
	void			RemoveElement(const std::string& Name, bool Delete = true)
	{
		RemoveElement(Getkey(Name), Delete);
	}

	/// number of elements
	unsigned long	GetElementC() const
	{
		return (unsigned long)m_Set.size();
	}
	
	/// get the CRC32 number from the key.. usefull for caching the key
	unsigned long	Getkey(const std::string& Name) const
	{
		return CRC32::FastHash(Name, m_IgnoreCase);
	}

	typedef void	(*FindSetCB) (T, void* second); // callback for effect param
	void			ForEach(FindSetCB pCB, void* second)
	{
		for (typename ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
		{
			pCB((*It).second, second);
		}
	}
protected:
	struct	Element
	{
		T				second;
		unsigned long	key;
	};
	
	typedef std::list<Element>					ElementList;

	ElementList		m_Set;
	bool			m_DeleteSet;
	bool			m_IgnoreCase;
};

} //namespace num
#endif  // _NAMED_VECTOR_H_
